#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>

using namespace std;

template<class T>
T f(T x) {
	return cos(x);
}

template<class T>
T pochodna(T x) {
	return -sin(x);
}

template<class T>
T progresywna(T x, T h) {
	return (f(x + h) - f(x)) / h;
}

template<class T>
T centralna(T x, T h) {
	return (f(x + h) - f(x - h)) / (static_cast<T>(2.0) * h);
}

template<class T>
T wsteczna(T x, T h) {
	return (f(x) - f(x - h)) / h;
}


template<class T>
T wsteczna_3p(T x, T h) {
	static T one = 1.0;
	static T two = 2.0;
	static T three = 3.0;
	return (((one / two) * f(x - two * h)) - two * f(x - h) + (three / two) * (f(x))) / h;
}

template<class T>
T progresywna_3p(T x, T h) {
	static T one = 1.0;
	static T two = 2.0;
	static T three = 3.0;
	return ((-three / two) * (f(x)) + two * f(x + h) - (one / two) * (f(x + two * h))) / h;
}




template<class T>
void getData(string fileName, int n){
	T a = 0.0;
	T b = M_PI_4; /* PI / 4 */
	T c = M_PI_2; /* PI / 2 */
	T h = 0.1;
	T res[7][1000];
	T array_h[1000];


	    for(int i = 0; i < n; i++)
	    {

	    		/* Początek przedziału. */
	            res[0][i] = log10(fabs(pochodna(a) - progresywna(a, h)));
	            res[1][i] = log10(fabs(pochodna(a) - progresywna_3p(a,  h)));

	            /* Środek przedziału. */
	            res[2][i] = log10(fabs(pochodna(b) - progresywna(b, h)));
	            res[3][i] = log10(fabs(pochodna(b) - wsteczna(b, h)));
	            res[4][i] = log10(fabs(pochodna(b) - centralna(b, h)));

	            /* Koniec przedziału */
	            res[5][i] = log10(fabs(pochodna(c) - wsteczna(c, h)));
	            res[6][i] = log10(fabs(pochodna(c) - wsteczna_3p(c, h)));

	            array_h[i] = log10(h);
	            h /= static_cast<T>(10.0);
	    }

		ofstream file, file2;
		file.open( fileName.c_str() );
		file2.open( (fileName+"2").c_str() );

		file2 << setw(15) << "h" << setw(15) << "prog_2p_pocz" << setw(15) << "prog_3p_pocz" << setw(15)
				<< "prog_2p_srod" << setw(20) << "wstecz_2p_srod" << setw(20) << "cent_2p_srod" << setw(20)<< "wstecz_2p_konie"<< setw(20) << "wstecz_3p_koniec" << setw(15) ;
		file2 << endl;
		for (int j = 0; j < n; j++) {
			file2 << setw(15) << setprecision(4) << fixed << array_h[j]<< "\t";
			file << setw(15) << setprecision(4) << fixed << array_h[j]<< "\t";
			for(int i=0; i<7; i++){
				file << fixed << setw(15) << res[i][j] << "\t";
				file2 << fixed << setw(15) << res[i][j] << "\t";
			}
			file  << endl;
			file2 << endl;
		}

	    file.close();
	    file2.close();

}



int main(int argc, char *argv[])
{
	getData<float>("float.dat", 15);
	getData<double>("double.dat", 30);

    return 0;
}




